package com.example.demo.Aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

@Aspect // 定义一个切面,表明此类为一个切面
@Component
public class UserAspect {
    //切点： 定义切点(设置拦截规则)，这⾥使⽤ AspectJ 表达式语法
    @Pointcut("execution(* com.example.demo.controller.UserController.* (..))")
    public void pointcut() {
    }

    //通知： 定义 pointcut() 切点的前置通知，表示在执行目标方法之前执行前置通知方法
    @Before("pointcut()")
    public void doBefore() {
        System.out.println("前置通知：被执行了 ！");
    }

    // 后置通知
    @After("pointcut()")
    public void doAfter() {
        System.out.println("执⾏后置通知 After ⽅法");
    }

    // return 之前通知
    @AfterReturning("pointcut()")
    public void doAfterReturning() {
        System.out.println("执⾏ AfterReturning ⽅法");
    }

    // 抛出异常之前通知
    @AfterThrowing("pointcut()")
    public void doAfterThrowing() {
        System.out.println("执⾏ doAfterThrowing ⽅法");
    }

    // 添加环绕通知：将整个目标方法包裹起来了
//    @Around("pointcut()")
//    public Object doAround(ProceedingJoinPoint joinPoint) {
//        Object obj = null;
//        System.out.println("Around ⽅法开始执⾏");
//        long start = System.currentTimeMillis();
//        try {
//            // 执⾏拦截⽅法，以及拦截方法所对应的相应通知
//            obj = joinPoint.proceed();
//        } catch (Throwable throwable) {
//            throwable.printStackTrace();
//        }
//        System.out.println("Around ⽅法结束执⾏");
//        long end = System.currentTimeMillis();
//        System.out.println(joinPoint.getSignature().getName() + "方法执行花费了 " + (end - start) + " ms");
//        return obj;
//    }


    // 使用环绕通知和 StopWatch 来记录拦截方法花费的时间
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        StopWatch stopWatch = new StopWatch();
        Object obj = null;
        System.out.println("Around ⽅法开始执⾏");
        stopWatch.start();
        try {
            obj = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("Around ⽅法结束执⾏");
        stopWatch.stop();
        System.out.println(joinPoint.getSignature().getName() + "方法执行花费了 " + stopWatch.getTotalTimeMillis() + " ms");
        return obj;
    }
}

